#include "table.h"

bucket::bucket ()
{
  list = NULL;
}

bucket::bucket (const bucket& temp)
{
  copy (temp);
}

bucket::~bucket ()
{
  lnode *temp;

  while (list)
  {
	temp = list;
	list = list->next;
	delete temp;
  }
}

lnode* bucket::find_node (string key)
{
  lnode *curr = list;
  while (curr && (curr->key != key))
	curr = curr->next;
  if (curr)
	return curr;
  else
	return curr = NULL;	     // node not found
}

void bucket::add_first (string key, int value)
{
  list = make_node (key, value, list);
}

void bucket::del (string key)
{
  lnode *curr = list, *prev = NULL;
  while (curr && (curr->key != key))
  {
	prev = curr;
	curr = curr->next;
  }
  if (curr)                  // node is found
  {
	if (prev)
	  prev = curr->next;     // in the middle of the list
	else
	  list = curr->next;     // at the beginning
	delete curr;
  }
}

void bucket::print ()
{
  lnode *curr = list;
  while (curr)
  {
	cout << "Key: " << curr->key << ".             Number of occurrance: ";
	cout << curr->val << endl;
	curr = curr->next;
  }
}

void bucket::copy (const bucket& temp)
{
  lnode *temp_curr = temp.list, *temp_list, *prev;

  list = new lnode;
  temp_list = list;
  while (temp_curr)
  {
	temp_list->key = temp_curr->key;
	temp_list->val = temp_curr->val;
	temp_list->next = new lnode;
	temp_curr = temp_curr->next;
	prev = temp_list;
	temp_list = temp_list->next;
  }
  // now modify the next pointer in the last list item to point to null instead
  // of pointing to a new lnode;
  delete temp_list;
  prev->next = NULL;
}

lnode* bucket::make_node (string key_val, int value, lnode *nxt_node)
{
  lnode *temp;

  temp = new lnode;
  temp->key = key_val;
  temp->val = value;
  temp->next = nxt_node;
  return temp;
}

bucket& bucket::operator= (const bucket& temp)
{
  lnode *prev = list;

  while (list)
  {
	prev = list;
	list = list->next;
	delete prev;
  }
  // delete the last item
  copy (temp);
  return *this;
}

table::table ()
{
  size = 100;
  buck = new bucket[size];
}

table::table (int max_size = 100)
{
  size = max_size;
  buck = new bucket[size];
}

table::table (const table& temp)
{
  copy (temp);
}

table::~table ()
{
  delete [] buck;
}

void table::name (string obj_name)
{
  Name = obj_name;
}

string table::name ()
{
  return Name;
}

void table::add (string key, int value = 1)
{
  int code;
  lnode *temp = find_node (key);

  if (temp)
	temp->val += value;
  else
  {
	code = hash (key);
	buck[code].add_first (key, value);
  }
}

int table::find (string key)
{
  lnode *temp = find_node (key);

  if (temp)
	return temp->val;
  else
	return -1;
}

void table::del (string key)
{
  int code = hash (key);
  buck[code].del (key);
}

void table::print ()
{
  for (int i = 0; i < size; i++)
	buck[i].print ();
}

void table::copy (const table& a)
{
  Name = a.Name;
  size = a.size;
  for (int i = 0; i < size; i++)
	buck[i] = a.buck[i];
}

int table::hash (string m)
{
  int length = m.len (), sum = 0;
  for (int i = 0; i < length; i++)
	sum += (int) m[i];
  return sum % size;
}

lnode* table::find_node(string m)
{
  int code;
  lnode *result = NULL;

  code = hash (m);
  result = buck[code].find_node (m);
  return result;
}
